package com.guopiao.vat.common.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;

public class ThreeDesUtils {

  private static final String hexString="0123456789ABCDEF";
  private static final String IV = "1234567-";

  public static void main(String[] args) throws Exception {
    byte[] key = new BASE64Decoder().decodeBuffer("n7LDq5TMehC3MWZl7ViVXuhVnpZ9Mug0");

    byte[] keyiv = {1, 2, 3, 4, 5, 6, 7, 8};

    byte[] data = "000,e12345,20180301112059,100,1,1,111,".getBytes("UTF-8");

    System.out.println("ECB加密解密");
    byte[] str3 = des3EncodeECB(key, data);
    String str4 = des3DecodeECB(key, str3);
    System.out.println(new BASE64Encoder().encode(str3));
//    System.out.println(des3DecodeECB("n7LDq5TMehC3MWZl7ViVXuhVnpZ9Mug0","hN6K4ZCpF8hXWiXD500N1Kbzlz6Y38Q5WtnXsAjMW3Q="));

    System.out.println(str4);
    System.out.println("-----------------------------");
    System.out.println("CBC加密解密");
    byte[] str5 = des3EncodeCBC(key, keyiv, data);
    byte[] str6 = des3DecodeCBC(key, keyiv, str5);
    System.out.println(new BASE64Encoder().encode(str5));
    System.out.println(new String(str6, "UTF-8"));
  }

  /**
   * ECB加密,不要IV
   *
   * @param key 密钥
   * @param data 明文
   * @return Base64编码的密文
   */
  public static byte[] des3EncodeECB(byte[] key, byte[] data)
      throws Exception {
    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(key);
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);
    Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, deskey);
    byte[] bOut = cipher.doFinal(data);
    return bOut;
  }

  /**
   * ECB解密,不要IV
   *
   * @param key 密钥
   * @param data Base64编码的密文
   * @return 明文
   */
  public static String des3DecodeECB(byte[] key, byte[] data)
      throws Exception {
    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(key);
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);
    Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, deskey);
    byte[] bOut = cipher.doFinal(data);
    return new String(bOut, "UTF-8");
  }

  /**
   * DESCBC解密
   *
   * @param src
   *            数据源
   * @param key
   *            密钥，长度必须是8的倍数
   * @return 返回解密后的原始数据
   * @throws Exception
   */
  public static String decryptDESCBC( String src,  String key) throws Exception {
    // --通过base64,将字符串转成byte数组
    final BASE64Decoder decoder = new BASE64Decoder();
    final byte[] bytesrc = decoder.decodeBuffer(src);

    // --解密的key
    final DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
    final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    final SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

    // --向量
    final IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));

    // --Chipher对象解密Cipher.getInstance("DES")就是采用ECB模式,cipher.init(Cipher.DECRYPT_MODE,
    // secretKey)就可以了.
    final Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
    final byte[] retByte = cipher.doFinal(bytesrc);

    return new String(retByte);

  }

  /**
   * ECB解密,不要IV
   *
   * @param data
   * @return 明文
   */
  public static String des3DecodeECB(String tokenKey, String data)
      throws Exception {

    byte[] key = new BASE64Decoder().decodeBuffer(tokenKey);

    final BASE64Decoder decoder = new BASE64Decoder();
    final byte[] bytesrc = decoder.decodeBuffer(data);

    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(key);
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);
    Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, deskey);
    byte[] bOut = cipher.doFinal(bytesrc);
    return new String(bOut, "UTF-8");
  }
  /**
   * CBC加密
   *
   * @param key 密钥
   * @param keyiv IV
   * @param data 明文
   * @return Base64编码的密文
   */
  public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data)
      throws Exception {
    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(key);
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);
    Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
    IvParameterSpec ips = new IvParameterSpec(keyiv);
    cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
    byte[] bOut = cipher.doFinal(data);
    return bOut;
  }

  /**
   * CBC解密
   *
   * @param key 密钥
   * @param keyiv IV
   * @param data Base64编码的密文
   * @return 明文
   */
  public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data)
      throws Exception {
    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(key);
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);
    Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
    IvParameterSpec ips = new IvParameterSpec(keyiv);
    cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
    byte[] bOut = cipher.doFinal(data);
    return bOut;
  }

  //BASE64解密
  public static byte[] decryptBASE64(String key) throws Exception {
    return (new BASE64Decoder()).decodeBuffer(key);
  }

  //BASE64加密
  public static String encryptBASE64(byte[] key) throws Exception {
    return (new BASE64Encoder()).encodeBuffer(key);
  }
  /**
   * 字符串转为16进制
   * @param str
   * @return
   */
  public static String encode(String str)
  {
    //根据默认编码获取字节数组
    byte[] bytes=str.getBytes();
    StringBuilder sb=new StringBuilder(bytes.length*2);

    //将字节数组中每个字节拆解成2位16进制整数
    for(int i=0;i<bytes.length;i++)
    {
      sb.append(hexString.charAt((bytes[i]&0xf0)>>4));
      sb.append(hexString.charAt((bytes[i]&0x0f)>>0));
    }
    return sb.toString();
  }

}
